﻿using IdGen;
using KWT.DRG_DIP.Common;
using KWT.DRG_DIP.DB;
using KWT.DRG_DIP.DO.System;
using KWT.DRG_DIP.ISvc;
using KWT.DRG_DIP.PO.Basic;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace KWT.DRG_DIP.Svc
{
    public class JwtSvc : IJwtSvc
    {
        public EFContext ef { get; set; }
        public MainEFContext main { get; set; }
        public IIdGenerator<long> snow_id { get; set; }
        public (AccessToken access_token, Sys_RefreshToken refresh_token) Create(Sys_User user, string policy)
        {
            var handler = new JwtSecurityTokenHandler();

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new[]
                {
                    new Claim("UserID", user.UserID),
                    new Claim("TenantID", user.TenantID),
                    new Claim("RoleID", user.RoleID),
                    new Claim("Policy",policy),
                }),
                Expires = DateTime.UtcNow.AddSeconds(AppSettings.JWT.AccessTokenExpires), // 比较合理的值为 5~10 分钟，这里设置 30 秒只是作演示用
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSettings.JWT.SecurityKey)), SecurityAlgorithms.HmacSha256)
            };

            var token = handler.CreateToken(tokenDescriptor);
            var jwtToken = handler.WriteToken(token);
            var accessToken = new AccessToken()
            {
                Token = jwtToken,
                ExpiredIn = AppSettings.JWT.AccessTokenExpires
            };
            var refreshToken = new Sys_RefreshToken()
            {
                TokenID = "TK" + snow_id.CreateId().ToString(),
                Access_Token = jwtToken,
                Is_Used = false,
                Is_Revorked = false,
                UserID = user.UserID,
                Add_Date = DateTime.UtcNow,
                Exp_Date = DateTime.UtcNow.AddSeconds(AppSettings.JWT.RefreshTokenExpires),
                Token = _Tool.RandomString(25)
            };
            main.Add(refreshToken);
            var _user = main.Find<Sys_User>(user.UserID);
            _user.LastLoginTime = DateTime.Now;
            main.Attach(_user);
            main.SaveChanges();
            return (accessToken, refreshToken);
        }

        public (bool, string) Verify(string refresh_token)
        {
            var jwtTokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(AppSettings.JWT.SecurityKey);
            var paras = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = true,
                RequireExpirationTime = false,
                ClockSkew = TimeSpan.Zero
            };

            var storedRefreshToken = main.Set<Sys_RefreshToken>().FirstOrDefault(x => x.Token == refresh_token);

            if (storedRefreshToken == null)
            {
                return (false, "refresh_token不存在");
            }

            if (DateTime.UtcNow > storedRefreshToken.Exp_Date)
            {
                return (false, "refresh_token已过期，请重新登录！");
            }

            if (storedRefreshToken.Is_Used)
            {
                return (false, "refresh_token已被使用！");
            }

            if (storedRefreshToken.Is_Revorked)
            {
                return (false, "refresh_token已被回收！");
            }

            storedRefreshToken.Is_Used = true;
            var a = main.Set<Sys_RefreshToken>().Update(storedRefreshToken);
            var user = main.Find<Sys_User>(storedRefreshToken.UserID);
            var tenant = main.Find<Sys_Tenant>(user.TenantID);
            main.SaveChanges();
            var result = Create(user, tenant.UsePolicy);
            return (true, result.access_token.Token);

        }
    }
}
